﻿using UnityEngine;
using UnityEngine.Rendering;

/// <summary>
/// 单个摄像机的渲染过程
/// </summary>
public partial class CameraRenderer 
{
    // 渲染上下文环境
    ScriptableRenderContext context;
    
    Camera camera;
    
    // 命令缓冲区
    const string bufferName = "Render Camera";
    CommandBuffer buffer = new CommandBuffer {
        name = bufferName
    };
    
    // 存储剔除结果
    CullingResults cullingResults;
    
    // 获取内置的无光照Shader
    static ShaderTagId 
        unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit"),
        litShaderTagId = new ShaderTagId("CustomLit");
    
    // 光照
    Lighting lighting = new Lighting();

    /// <summary>
    /// 渲染
    /// </summary>
    public void Render (ScriptableRenderContext context, Camera camera, bool useDynamicBatching, bool useGPUInstancing) 
    {
        this.context = context;
        this.camera = camera;
        PrepareBuffer();
        PrepareForSceneWindow();
        // 物体剔除
        if (!Cull()) {
            return;
        }
        
        Setup();
        lighting.Setup(context, cullingResults);
        DrawVisibleGeometry(useDynamicBatching, useGPUInstancing);
        DrawUnsupportedShaders();
        DrawGizmos();
        Submit();
    }
    
    /// <summary>
    /// 对渲染上下文进行设置
    /// </summary>
    void Setup () 
    {
        // 设置相机属性
        context.SetupCameraProperties(camera);
        CameraClearFlags flags = camera.clearFlags; // 清除标志
        buffer.ClearRenderTarget(flags <= CameraClearFlags.Depth, 
            flags <= CameraClearFlags.Color, 
            flags == CameraClearFlags.Color ? camera.backgroundColor.linear : Color.clear); // 清空渲染目标
        buffer.BeginSample(SampleName); // 开始采样
        
        ExecuteBuffer();
    }
    
    /// <summary>
    /// 绘制可见几何体
    /// </summary>
    void DrawVisibleGeometry (bool useDynamicBatching, bool useGPUInstancing) 
    {
        var sortingSettings = new SortingSettings(camera) { criteria = SortingCriteria.CommonOpaque }; // 排序设置 -- 排序规则
        var drawingSettings = new DrawingSettings(unlitShaderTagId, sortingSettings)
        {
            enableDynamicBatching = useDynamicBatching, // 使用动态批处理
            enableInstancing = useGPUInstancing // 启用GPU实例化
        }; // 绘制设置 -- shader、排序
        drawingSettings.SetShaderPassName(1, litShaderTagId);
        var filteringSettings = new FilteringSettings(RenderQueueRange.opaque); // 过滤设置 -- 过滤透明物体
        
        // 绘制可见对象
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filteringSettings
        );
        
        // 绘制天空盒
        context.DrawSkybox(camera);
        
        // 绘制透明物体
        sortingSettings.criteria = SortingCriteria.CommonTransparent;
        drawingSettings.sortingSettings = sortingSettings;
        filteringSettings.renderQueueRange = RenderQueueRange.transparent;
        
        context.DrawRenderers(
            cullingResults, ref drawingSettings, ref filteringSettings
        );
    }
    
    /// <summary>
    /// 提交绘制内容 -- 显示到屏幕上
    /// </summary>
    void Submit () {
        buffer.EndSample(SampleName); // 结束
        ExecuteBuffer();
        context.Submit();
    }
    
    /// <summary>
    /// 执行缓冲区
    /// </summary>
    void ExecuteBuffer () {
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }
    
    /// <summary>
    /// 剔除相机视野外的物体
    /// </summary>
    /// <returns></returns>
    bool Cull ()
    {
        if (camera.TryGetCullingParameters(out ScriptableCullingParameters p)) 
        {
            cullingResults = context.Cull(ref p);
            return true;
        }
        return false;
    }
}